package com.zlk.algorithm.bit;


import org.junit.Test;

import java.util.Arrays;

/**
 * @Title: Index   位运算demo
 * Company: zlk
 * @author: fsl
 * @version: 1.0
 * create date: 2022/8/15
 **/
public class Index {

    //基础概念
    //在Java中，数据类型用于定义变量的类型和范围。Java提供了一系列的原始数据类型，包括整数、浮点数、字符和布尔值等。这些数据类型在内存中占据不同的字节数。
    // 其中，整数类型包括byte、short、int和long。
    // 一个字节占八位  所以一个int 是32位 比如1  32显示是  0000 0000 0000 0000 0000 0000 0000 0001

    // int 按理说32位表示得数据范围有  0  -  2 的32次方-1  但是int有符号值
    // 第32位位符号位  0表示取整   1表示取负   所以整数范围表示 -2的31  至  2 的31次方-1

    @Test
    public void printBytes(){
        System.out.println("byte类型占用的字节数：" + Byte.BYTES);
        System.out.println("short类型占用的字节数：" + Short.BYTES);
        System.out.println("int类型占用的字节数：" + Integer.BYTES);
        System.out.println("long类型占用的字节数：" + Long.BYTES);
        System.out.println("float类型占用的字节数：" + Float.BYTES);
        System.out.println("double类型占用的字节数：" + Double.BYTES);
        System.out.println("char类型占用的字节数：" + Character.BYTES);
        System.out.println("boolean类型占用的字节数：" + Boolean.toString(false).getBytes().length);
    }


    /**
     * 如何打印一个int 数值 32位结果
     */
    @Test
    public void printIntByteVal(){
        System.out.println(getIntByteVal(4));
        System.out.println(getIntByteVal(5));
        System.out.println(getIntByteVal(6));
        System.out.println(getIntByteVal(7));
    }
    String getIntByteVal(int val){
        String res = "";
        for (int i = 31; i >=0; i--) {
            res += ((1 << i) & val) ==0?"0":"1";
        }
        return res;
    }

    //原码、反码与补码
    //原码:对一个正整数来说，所谓的原码，就是指一个整数对应的二进制，比如整数10的原码就是00001010。所以原码就是一个正整数原本对应的二进制形式。但负数的原码和正数却不一样，
    //    负数的原码要将正数原码的符号位(最高位)改为1，比如-10的原码就是10001010。
    //反码:正数的反码就是其原码，即正数的原码和反码完全相同。而负数的反码则是将原码中除符号位以外的所有位(数值位)都取反，即 0 变成 1，1 变成 0。如10的原码和反码都是00001010，
    //    而-10的原码是10001010，反码则是11110101。
    //补码:正数的补码就是其原码，所以正数的原码、反码、补码都相同。而负数的补码是其反码加1，-10的原码是10001010，反码则是11110101，补码则是11110110。我们可以认为，补码是在反码
    //    的基础上打了一个补丁，进行了一点修正，所以叫做“补码”。

    //getIntByteVal(-1) 他会表示成 11111111111111111111111111111
    // 为什么负数能表示能有2 的31 次方  负数最小值位 （1 0000 0000 0000 0000 ~  000）
    // 如何计算 将他 取反+1  1 1 后面31 个0  为什么会进位，此处理解只是这么表示因为
    // 正真计算机存储还是  1 0000 0000 0000 0000 ~  000
    // 然而为什么计算负数要取反+1  因为计算底层加减乘除都用的是2进制位运算  而不是 10进制计算 ，所以取反+1 就为了契合2进制位运算


    @Test
    public void test2(){
//        int a = Integer.MAX_VALUE;
//        System.out.println(getIntByteVal(a));
//        System.out.println(getIntByteVal(a >>> 1));
//        System.out.println(getIntByteVal(a >> 1));
//
//
//        a = Integer.MIN_VALUE;
//        System.out.println(getIntByteVal(a));
//        System.out.println(getIntByteVal(a >>> 1));
//        System.out.println(getIntByteVal(a >> 1));

        //由上结果显示  >> 为带符号右移动   >>>不带符号右移

//        int c =5;
//        System.out.println(c);
//        int d = -c;
//        System.out.println(d);
//        //取反+1
//        d = (~c+1);
//        System.out.println(d);
//
//        //系统最小值就是他本身
//        int aa = Integer.MIN_VALUE;
//        System.out.println(getIntByteVal(aa));
//        System.out.println(getIntByteVal(~aa+1));


        System.out.println(getIntByteVal(5));
        System.out.println(getIntByteVal(-3));
        System.out.println(getIntByteVal(-3+5));

    }


    //与运算（&）  也就是说只要有0，结果即为0                eg: 1001 & 1110 = 1000。
    //或运算（|）  运算法则为遇1得1。也就是说只要有1，结果即为1。eg: 1001 | 1110 = 1011
    //非运算（~）  运算法则为按位取反，也就是遇1取0,遇0取1。eg: ~1001 = 0110。
    //异或运算（^）运算法则为相同取0，不同取1。异为1，否则为0。eg: 1001 ^ 1110= 0111。






}
